﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MetroFramework;
using MetroFramework.Forms;
using MetroFramework.Controls;
using nClam;
using System.IO;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading;
using System.Collections;
using System.Media;
using TejashPlayer;
using System.Security.AccessControl;
using System.Security.Principal;
using BrightIdeasSoftware;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Management;
using System.Net.Http;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.Net;
using System.Net.Sockets;

namespace AntiVirus_Project
{
    public partial class Form1 : MetroForm
    {
#pragma warning disable 0618 // removes the obsolete warning
        [DllImport("process-killer.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int KillProcess(IntPtr handle, string proc_name);

        // 定义一个静态 logger 变量，其引用名为 "Program" 的 Logger 实例
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(Form1));

        private string my_location = string.Empty;
        private Thread search = null;
        private string loc_to_search = string.Empty;
        private bool scanning = false;
        private bool suspended = false;
        private string wildcard = "*.*";
        private string smart_ext = "*.exe|*.cpl|*.reg|*.ini|*.bat|*.com|*.dll|*.pif|*.lnk|*.scr|*.vbs|*.ocx|*.drv|*.sys";
        private string[] files = null;
        private ArrayList watchers = new ArrayList();
        private DateTime sch_time;
        private string sch_loc = string.Empty;
        private bool av_service_error = false;

        private ConsoleSetups con = new ConsoleSetups();
        private ServiceController service = new ServiceController();
        private UsbManager usb = new UsbManager();
        private History his = new History();
        private Quarantine quaran = new Quarantine();
        private Exclusion exclusion = new Exclusion();
        private Firewall fw = new Firewall();
        private FolderLocker locker = new FolderLocker();

        private ClamAVMonitor monitor; //= new ClamAVMonitor(@"C:\freshclam.dat"); // 替换为实际路径


        //main form ctor()
        public Form1()
        {
            CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
            my_location = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            monitor = new ClamAVMonitor(my_location + "\\engine\\DB\\freshclam.dat"); // 替换为实际路径
            monitor.StartMonitoring();

        }

        public static void SaveUdpServerConfig(string ipAddress, int port)
        {
            try
            {
                // 构建配置内容
                StringBuilder configContent = new StringBuilder();
                configContent.AppendLine("[UdpServer]");
                configContent.AppendLine($"IpAddress={ipAddress}");
                configContent.AppendLine($"Port={port}");

                // 将内容写入配置文件，覆盖原有内容
                File.WriteAllText("UdpServer.config", configContent.ToString(), Encoding.UTF8);

                // 可根据需要弹出提示，告知用户保存成功
                MessageBox.Show("UDP 服务器配置已成功保存！", "保存成功",
                                MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                // 捕获异常并提示，也可记录日志等
                MessageBox.Show($"保存配置时发生错误：{ex.Message}", "保存失败",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        // 加载配置到界面
        private void LoadConfigToUI()
        {
            var (ip, port) = ReadUdpServerConfig("UdpServer.config");
            this.metroTextBox1.Text = ip;
            this.metroTextBox2.Text = port.ToString();
        }

        // 添加事件处理方法
        private void SaveConfigButton_Click(object sender, EventArgs e)
        {
            // 验证IP格式
            if (!IPAddress.TryParse(this.metroTextBox1.Text, out _))
            {
                MessageBox.Show("请输入有效的IP地址！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // 验证端口
            if (!int.TryParse(this.metroTextBox2.Text, out int port) || port < 1 || port > 65535)
            {
                MessageBox.Show("请输入有效的端口号(1-65535)！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // 保存配置
            SaveUdpServerConfig(this.metroTextBox1.Text, port);
        }


        //setup the scanner engine
        private void SetupScannerEngine()
        {
            //setup the scanner engine path
            string temp = my_location + "\\engine\\";

            //write the correct engine configurations according to path
            StreamWriter writter = new StreamWriter(temp + "clamd.conf");
            writter.WriteLine("TCPSocket 3310");
            writter.WriteLine("MaxThreads 2");
            writter.WriteLine("LogFile " + temp + "clamd.log");
            writter.WriteLine("DatabaseDirectory " + temp + "db");
            writter.Close();

            string fc = temp + "freshclam.conf";
            if(!File.Exists(fc)){
            //write the correct engine configurations according to path
                StreamWriter upwritter = new StreamWriter(fc);
                upwritter.WriteLine("DatabaseMirror database.clamav.net");
                upwritter.WriteLine("DNSDatabaseInfo current.cvd.clamav.net");
                upwritter.WriteLine("UpdateLogFile " + temp + "freshclam.log");
                upwritter.Close();
            }else{
                //file exist
                string databaseMirror = "database.clamav.net";
                string dns = "current.cvd.clamav.net";
                using (StreamReader reader = new StreamReader(fc))
                {
                    string line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        // 查找包含 DatabaseMirror 的行
                        if (line.StartsWith("DatabaseMirror"))
                        {
                            // 分割字符串，去除前面的关键字和空格
                            string[] parts = line.Split(new[] { ' ', '=', ';' }, StringSplitOptions.RemoveEmptyEntries);
                            if (parts.Length > 1)
                            {
                                databaseMirror = parts[parts.Length - 1]; // 获取最后一个部分，即database.clamav.net
                            }                            
                        }
                        // 查找包含 DatabaseMirror 的行
                        if (line.StartsWith("DNSDatabaseInfo"))
                        {
                            // 分割字符串，去除前面的关键字和空格
                            string[] parts = line.Split(new[] { ' ', '=', ';' }, StringSplitOptions.RemoveEmptyEntries);
                            if (parts.Length > 1)
                            {
                                dns = parts[parts.Length - 1]; // 获取最后一个部分，即database.clamav.net
                            }
                        }
                    }
                }
                StreamWriter upwritter = new StreamWriter(fc);
                upwritter.WriteLine("DatabaseMirror " + databaseMirror);
                upwritter.WriteLine("DNSDatabaseInfo " + dns);
                upwritter.WriteLine("UpdateLogFile " + temp + "freshclam.log");
                upwritter.Close(); 
                metroTxtMirr.Text = databaseMirror;
                metroTxtDns.Text = dns;                               
            }


            //insert the correct registry settings according to path
            //I am not using try catch block because, I am already running as admin
            //so probably it will not give error, will fix this if gives error in future 
            RegistryKey key;
            key = Microsoft.Win32.Registry.LocalMachine.CreateSubKey("Software\\ClamAV\\");
            key.SetValue("ConfigDir", temp);
            key.Close();
            key = Microsoft.Win32.Registry.LocalMachine.CreateSubKey("Software\\ClamAV\\");
            key.SetValue("DataDir", temp + "db");
            key.Close();


            //Install the AV scanner service
            con.RunExternalExe(temp + "clamd.exe", "--install -c " + temp + "clamd.conf");

            //install the AV updater service
            con.RunExternalExe(temp + "freshclam.exe", "--install --config-file=" + temp + "freshclam.conf");

            //start the antivirus services...
            try
            {
                string status = string.Empty;
                service.ServiceName = "FreshClam";
                status = service.Status.ToString();
                if (status == "Stopped"){
                    //fix clamav bug, change config file
                    string serviceName = "FreshClam";
                    string keyPath = $@"SYSTEM\CurrentControlSet\Services\{serviceName}";
                    RegistryKey serviceKey = Registry.LocalMachine.OpenSubKey(keyPath, true);

                    if (serviceKey != null)
                    {
                        // 修改ImagePath值
                        serviceKey.SetValue("ImagePath", temp + "freshclam.exe" + " --daemon --service-mode --config-file=" + temp + "freshclam.conf");

                        // 关闭注册表键
                        serviceKey.Close();

                    }
                    else
                    {
                        log.Info($"The registry key '{keyPath}' does not exist.");
                    }
                    service.Start();
                    this.metroLabelUpdtime.Text = GetNewestUpdateTimeInDBDirectory();
                }


                status = service.Status.ToString();
                if (status != "Running"){
                    log.Warn("freshclam service does not run");
                }

                status = string.Empty;
                service.ServiceName = "ClamD";
                status = service.Status.ToString();
                if (status == "Stopped"){
                    //fix clamav bug, change config file
                    string serviceName = "ClamD";
                    string keyPath = $@"SYSTEM\CurrentControlSet\Services\{serviceName}";
                    RegistryKey serviceKey = Registry.LocalMachine.OpenSubKey(keyPath, true);

                    if (serviceKey != null)
                    {
                        // 修改ImagePath值
                        serviceKey.SetValue("ImagePath", temp + "clamd.exe" + " --daemon --service-mode -c " + temp + "clamd.conf");

                        // 关闭注册表键
                        serviceKey.Close();

                    }
                    else
                    {
                        log.Info($"The registry key '{keyPath}' does not exist.");
                    }
                    service.Start();
                }
                status = service.Status.ToString();
                if (status!= "Running"){
                    log.Error("Clamd service failed to run");
                }else{
                    log.Info("Start freshclam and clamd service");
                }
            }
            catch(Exception ex)
            {
                pictureBox1.Image = Properties.Resources.unsecured;
                pictureBox3.Image = Properties.Resources.cross;
                av_service_error = true;
                MetroFramework.MetroMessageBox.Show(this, "无法启动防病毒服务，请尝试重启应用程序，或参阅帮助手册了解如何手动启动服务。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                log.Error("无法启动防病毒服务，请尝试重启应用程序，或参阅帮助手册了解如何手动启动服务。" + ex);
            }
        }

        //stops the scanner services
        private void StopScannerEngine()
        {
            try
            {
                string status = string.Empty;
                service.ServiceName = "FreshClam";
                service.Stop();

                status = string.Empty;
                service.ServiceName = "ClamD";
                service.Stop();
            }
            catch { }
        }

        //override close
        protected override void WndProc(ref Message m)
        {
            DialogResult dr;
            if (m.Msg == 0x0010)
            {
                dr = MetroFramework.MetroMessageBox.Show(this,"您正在关闭简洁杀毒软件，关闭后您的电脑将不再安全。确定要关闭吗?", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (dr == DialogResult.No)
                    return;
                notifyIcon1.Dispose();
                Properties.Settings.Default.usb_auto = listenUSB.Checked;
                Properties.Settings.Default.real_scan = realToggle.Checked;
                Properties.Settings.Default.smart = smart_Toggle.Checked;
                Properties.Settings.Default.history = historyToggle.Checked;
                Properties.Settings.Default.Save();
                StopScannerEngine();
                if(scanning)
                {
                    try
                    {
                        search.Abort();
                    }
                    catch { }
                }
            }
            base.WndProc(ref m);
        }
        public static void RegisterToStartup()
        {
            // 获取本地机器的注册表键
            RegistryKey startupKey = Registry.CurrentUser.OpenSubKey(
                "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
                true);

            // 获取应用程序的执行路径
            string applicationPath = Application.ExecutablePath;

            // 写入注册表，使程序开机启动
            startupKey.SetValue(Application.ProductName, applicationPath);

            // 关闭注册表键
            startupKey.Close();
        }

        public static void UnregisterFromStartup()
        {
            // 同样的逻辑，只不过这次是移除启动项
            RegistryKey startupKey = Registry.CurrentUser.OpenSubKey(
                "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
                true);

            if (startupKey.GetValue(Application.ProductName) != null)
            {
                // 移除启动项
                startupKey.DeleteValue(Application.ProductName);
            }

            startupKey.Close();
        }
        public string GetNewestUpdateTimeInDBDirectory()
        {
            string cur = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            string directoryPath = cur + "\\engine\\DB\\";
            // 获取指定目录及其子目录下所有.db文件的信息
            var files = Directory.EnumerateFiles(directoryPath, "*.*", SearchOption.AllDirectories)
                                .Select(filePath => new FileInfo(filePath));

            // 找出最新更新时间的文件
            DateTime? newestUpdateTime = files.Max(file => file.LastWriteTimeUtc);

            if (newestUpdateTime.HasValue)
            {
                DateTime now = DateTime.Now; // 获取当前时间
                DateTime newestUpdateLocalTime = newestUpdateTime.Value.ToLocalTime(); // 转换为本地时间以便于用户理解

                TimeSpan timeDifference = now - newestUpdateLocalTime;

                // 计算天数、小时数和分钟数
                int days = timeDifference.Days;
                int hours = timeDifference.Hours;
                int minutes = timeDifference.Minutes;

                // 如果时间差小于一天，则不需要显示天数
                string timeDifferenceStr = "";
                if (days == 0)
                {
                    if(hours == 0){
                        timeDifferenceStr = $"{minutes}分钟前";
                    }else{
                        timeDifferenceStr = $"{hours}小时{minutes}分钟前";
                    }
                }
                else
                {
                    timeDifferenceStr = $"{days}天{hours}小时{minutes}分钟前";
                }
                return timeDifferenceStr; // 格式化为字符串
            }
            else
            {
                //未找到任何.db文件！
                return null;
            }
        }
        //form load
        private void Form1_Load(object sender, EventArgs e)
        {
            RegisterToStartup();
            metroTabControl1.SelectedIndex = 0;
            metroTabControl2.SelectedIndex = 0;
            metroProgressBar1.Maximum = 100;
            metroProgressBar1.Minimum = 0;
            metroProgressBar1.Value = 0;
            metroTile2.Enabled = false;
            metroTile3.Enabled = false;
            realToggle.Checked = Properties.Settings.Default.real_scan;
            listenUSB.Checked = Properties.Settings.Default.usb_auto;
            smart_Toggle.Checked = Properties.Settings.Default.smart;
            historyToggle.Checked = Properties.Settings.Default.history;
            metroProgressSpinner1.Visible = false;

            SetupScannerEngine(); // setup the scanner engine

            //start the usb monitor
            usb.StateChanged += new UsbStateChangedEventHandler(DoStateChanged);

            // do proper adjustment according to real time and auto usb scan settings
            realToggle_CheckedChanged(sender, e);
            listenUSB_CheckedChanged(sender, e);

            // file system watcher
            string[] drives = Directory.GetLogicalDrives();
            DriveInfo di = null;
            for(int i=0;i<drives.Length;i++)
            {
                di = new DriveInfo(drives[i]);
                if (di.IsReady)
                {
                    FileSystemWatcher watcher = new FileSystemWatcher();
                    watcher.Filter = "*.*";
                    watcher.Path = drives[i];
                    watcher.IncludeSubdirectories = true;
                    watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite| NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.Attributes;
                    watcher.Created += new FileSystemEventHandler(RealTime);
                    watcher.Renamed += new RenamedEventHandler(RealTime);
                    //watcher.Changed += new FileSystemEventHandler(RealTime);
                    watcher.InternalBufferSize = 4058;
                    watcher.EnableRaisingEvents = true;
                    watchers.Add(watcher);
                }
            }

            //firewall
            if (fw.firewallOn)
            {
                pictureBox2.Image = Properties.Resources.fine;
                metroLabel2.Text = "防火墙已启用";
                firewallToggle.Checked = true;
                foreach (string s in fw.GetAuthorizedAppPaths())
                    listBox1.Items.Add(s);
            }
            else
            {
                pictureBox2.Image = Properties.Resources.cross;
                metroLabel2.Text = "防火墙已关闭";
                firewallToggle.Checked = false;
            }

            //loads the history
            if(historyToggle.Checked)
            {
                for(int i=0;i<his.file_names.Count;i++)
                {
                    objectListView2.AddObject(new InfectionObject(his.file_names[i],his.vir_name[i]));
                }
            }

            //show the quarantine files
            foreach (string s in quaran.QuarantineItems())
                listBox2.Items.Add(s);

            //shows the exclusions
            foreach (string s in exclusion.exclusions)
                listBox3.Items.Add(s);

            //Everything is completed, now play a greet music and show balloon
            SoundPlayer snd = new SoundPlayer(Properties.Resources.ready);
            snd.Play();
            notifyIcon1.ShowBalloonTip(5, "简洁杀毒", "您的电脑是安全的", ToolTipIcon.Info);
            log.Info("Fengping AV is started successfully.");
        }

        // start scan
        private void metroTile1_Click(object sender, EventArgs e)
        {
            if(av_service_error)
            {
                MetroFramework.MetroMessageBox.Show(this, "杀毒软件未运行，请重启该软件或参阅帮助手册进行故障排查。", "警告", MessageBoxButtons.OK, MessageBoxIcon.Error);
                log.Error("杀毒软件未运行，请重启该软件或参阅帮助手册进行故障排查。");
                return;
            }

            if(metroRadioButton2.Checked) //quick
            {
                if(!scanning)
                {
                    loc_to_search = Path.GetPathRoot(Environment.SystemDirectory);
                    search = new Thread(new ThreadStart(ScanFolder));
                    search.Start();
                }
                return;
            }

            if (metroRadioButton3.Checked) // scan a file
            {
                openFileDialog1.Title = "请先选择文件";
                openFileDialog1.Multiselect = false;
                openFileDialog1.CheckPathExists = true;
                openFileDialog1.FileName = "";
                openFileDialog1.Filter = "All files|*.*";
                openFileDialog1.SupportMultiDottedExtensions = false;

                if (DialogResult.OK == openFileDialog1.ShowDialog())
                {
                    ScanFile(openFileDialog1.FileName, false);
                }
                return;
            }
            
            if(metroRadioButton4.Checked) // custom folder
            {
                if (scanning == true)
                {
                    MetroFramework.MetroMessageBox.Show(this, "请等待, 文件扫描正在进行中.", "等待", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
                folderBrowserDialog1.Description = "选择您的文件夹或驱动器";
                if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
                {
                    loc_to_search = folderBrowserDialog1.SelectedPath;
                    search = new Thread(new ThreadStart(ScanFolder));
                    search.Start();
                }
                return;
            }

            MetroFramework.MetroMessageBox.Show(this, "请先选择扫描类型", "错误", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        // 读取配置文件中的UDP服务器设置
        private (string ipAddress, int port) ReadUdpServerConfig(string configPath)
        {
            try
            {
                if (!File.Exists(configPath))
                {
                    log.Warn($"配置文件不存在: {configPath}，使用默认值");
                    return ("127.0.0.1", 30010);
                }

                var config = File.ReadAllLines(configPath)
                    .Where(line => !string.IsNullOrWhiteSpace(line) && !line.TrimStart().StartsWith("#"))
                    .Select(line => line.Split(new[] { '=' }, 2))
                    .ToDictionary(
                        parts => parts[0].Trim(),
                        parts => parts.Length > 1 ? parts[1].Trim() : string.Empty,
                        StringComparer.OrdinalIgnoreCase
                    );

                // 获取 IP 地址（传统方式）
                string ipAddress = "127.0.0.1";
                if (config.ContainsKey("IpAddress"))
                {
                    ipAddress = config["IpAddress"];
                }

                // 获取端口（传统方式）
                int port = 30010;
                string portStr;
                if (config.ContainsKey("Port") && 
                    int.TryParse(config["Port"], out int parsedPort))
                {
                    port = parsedPort;
                }

                return (ipAddress, port);
            }
            catch (Exception ex)
            {
                log.Error($"读取配置文件失败: {ex.Message}，使用默认值");
                return ("127.0.0.1", 30010);
            }
        }

        //scan the folder or file
        private int ScanFile(string loc, bool silent)
        {
            if(av_service_error)
            {
                MetroFramework.MetroMessageBox.Show(this, "杀毒软件未运行，请重启该软件或参阅帮助手册进行故障排查。", "警告", MessageBoxButtons.OK, MessageBoxIcon.Error);
                log.Error("杀毒软件未运行，请重启该软件或参阅帮助手册进行故障排查。");
                return 0;
            }

            int ret = 0;
            if (File.Exists(loc))
            {
                var clam = new ClamClient("localhost", 3310);
                //FIXME:未处理服务没启动的异常
                var scanResult = clam.ScanFileOnServer(loc);
                switch (scanResult.Result)
                {
                    case ClamScanResults.Clean:
                        if (!silent)
                            MetroFramework.MetroMessageBox.Show(this, "文件是干净的，未被感染。", "良好", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        ret = 0;
                        break;
                    case ClamScanResults.VirusDetected:
                        {
                            if (!silent)
                            {
                                DialogResult dr = MetroFramework.MetroMessageBox.Show(this, "文件已被感染\n病毒: " + scanResult.InfectedFiles.First().VirusName + "\n是否要删除?", "发现病毒", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                                if (dr == DialogResult.Yes)
                                    try
                                    {
                                        File.Delete(loc);
                                    }
                                    catch { }
                            }
                            try
                            {
                                // 记录警告日志
                                log.Warn("文件感染病毒，文件名称为:" + loc + "病毒名称为:" + scanResult.InfectedFiles.First().VirusName);
                            
                                // 配置文件读取服务端ip和端口
                                string configPath = "UdpServer.config";
                                var (serverIpSTR, serverPort) = ReadUdpServerConfig(configPath);

                                string fileFullPath = Path.GetFullPath(loc); // 获取文件绝对路径
                                string virusName = scanResult.InfectedFiles.First().VirusName;
                               // 获取当前本地时间
                                DateTime localTime = DateTime.Now;

                                // 格式化为带时区偏移的字符串（例如：2025-07-04T15:30:20+08:00）
                                string timestamp = localTime.ToString("yyyy-MM-ddTHH:mm:sszzz");


                                // 获取主机名和IP地址
                                string hostName = Dns.GetHostName();
                                string hostIp = string.Empty;
                                try
                                {
                                    IPHostEntry hostEntry = Dns.GetHostEntry(hostName);
                                    foreach (IPAddress ip in hostEntry.AddressList)
                                    {
                                        if (ip.AddressFamily == AddressFamily.InterNetwork)
                                        {
                                            hostIp = ip.ToString();
                                            break;
                                        }
                                    }
                                }
                                catch 
                                {
                                    log.Error("获取主机ip或主机名失败");
                                }

                                // 手动创建 UDP 客户端
                                UdpClient client = new UdpClient();
                                try
                                {
                                    IPAddress serverIp = IPAddress.Parse(serverIpSTR); 
                                    // int serverPort = 30010; 
                                    IPEndPoint serverEndpoint = new IPEndPoint(serverIp, serverPort);

                                    string trimmedVirusName = virusName.Trim();

                                    string message = $"{timestamp} {hostName} AntiVirusScanner:{hostIp},{fileFullPath},{trimmedVirusName}";
                                    byte[] data = Encoding.UTF8.GetBytes(message); // Syslog通常使用ASCII编码


                                    log.Info(data);
                                    client.Send(data, data.Length, serverEndpoint);
                                    log.Info("已发送 UDP 数据: " + message);
                                }
                                catch (Exception ex)
                                {
                                    // 捕获并记录发送过程中的异常（如网络不可达等）
                                    log.Error("UDP 发送失败: " + ex.Message);
                                }
                                finally
                                {
                                    // 手动关闭客户端，释放网络资源
                                    client.Close();
                                }
                                break;
                            }
                            
                            catch (Exception ex)
                            {
                                log.Error("发送UDP通知失败", ex);
                            }

                            ret = 1;
                        }
                        break;
                }
                return ret;
            }
            else
            {
                if(!silent)
                    MetroFramework.MetroMessageBox.Show(this, "待扫描的文件非法", "警告", MessageBoxButtons.OK, MessageBoxIcon.Error);
                ret = 3;
                return ret;
            }
        }

        // infected file details to list
        private void AddToResult(string file, string vir_name)
        {
            string[] row1 = { vir_name };
            Invoke(new Action(() =>
            {
                ListViewItem item = objectListView1.FindItemWithText(file);
                if(item==null)
                {
                    objectListView1.AddObject(new InfectionObject(file, vir_name));
                    if (historyToggle.Checked)
                    {
                        his.AddHistory(file, vir_name); // add to history
                        objectListView2.AddObject(new InfectionObject(file, vir_name)); //adds it to history list
                    }
                }
            }));
            log.Warn("添加到结果，文件: " + file + " 病毒名: " + vir_name);
        }

        //scan a folder
        private void ScanFolder()
        {
            if (av_service_error)
            {
                MetroFramework.MetroMessageBox.Show(this, "杀毒软件未运行，请重启该软件或参阅帮助手册进行故障排查。", "警告", MessageBoxButtons.OK, MessageBoxIcon.Error);
                try
                {
                    Invoke(new Action(() =>
                    {
                        metroProgressSpinner1.Visible = false;
                        metroProgressBar1.Value = 0;
                        metroLabel8.Text = "没有进行中的扫描...";
                        infec.Text = "感染文件数: 0";
                        metroTile2.Enabled = false;
                        metroTile3.Enabled = false;
                        metroTile1.Enabled = true;
                        curr_File.Text = "...";
                        metroRadioButton2.Enabled = true;
                        metroRadioButton3.Enabled = true;
                        metroRadioButton4.Enabled = true;
                    }));

                    scanning = false;
                    search.Abort();
                }
                catch { }
            }

            log.Info("开始扫描路径:"+loc_to_search);
            scanning = true;
            bool error = false;
            int infected = 0;

            //if it's a quick scan, first check all the running processes
            if (metroRadioButton2.Checked)
            {
                metroLabel8.Text = "扫描活动进程";
                notifyIcon1.ShowBalloonTip(5, "快速扫描", "扫描所有活动进程", ToolTipIcon.Info);
                foreach(string proc in GetAllRunningProcesses())
                {
                    if (File.Exists(proc))
                    {
                        try
                        {
                            var clam = new ClamClient("localhost", 3310);
                            var scanResult = clam.ScanFileOnServer(proc);
                            Invoke(new Action(() =>
                            {
                                curr_File.Text = proc;
                            }));

                            switch (scanResult.Result)
                            {
                                case ClamScanResults.VirusDetected:
                                    infected++;
                                    Invoke(new Action(() =>
                                    {
                                        infec.Text = "感染的文件数: " + infected.ToString();
                                    }));
                                    AddToResult(proc, scanResult.InfectedFiles.First().VirusName);
                                    break;
                            }
                        }
                        catch { error = true; }
                    }
                }
                Invoke(new Action(() =>
                {
                    curr_File.Text = "...";
                }));
            }//end of process scanning

            // normal scan process follows...

            Invoke(new Action(() =>
            {
                metroTile1.Enabled = false;
                metroTile2.Enabled = true;
                metroTile3.Enabled = true;
                metroLabel8.Text = "请稍候，我们正在准备待扫描的文件列表，这可能需要一些时间...";
                metroProgressSpinner1.Visible = true;
                metroProgressSpinner1.Show();

                metroRadioButton2.Enabled = false;
                metroRadioButton3.Enabled = false;
                metroRadioButton4.Enabled = false;
            }));
            
            if(smart_Toggle.Checked)
                files= getFiles(loc_to_search, smart_ext, SearchOption.AllDirectories);
            else
                files = getFiles(loc_to_search, wildcard, SearchOption.AllDirectories);
            int total = files.Length;

            Invoke(new Action(() =>
            {
                metroProgressSpinner1.Visible = false;
                metroLabel8.Text = "扫描: " + loc_to_search + " (" + total.ToString() + " 文件)";
                metroProgressBar1.Maximum = total;
                metroProgressBar1.Minimum = 0;
                metroProgressBar1.Value = 0;
                notifyIcon1.ShowBalloonTip(5, "简洁杀毒正在扫描...", "病毒扫描已启动", ToolTipIcon.Info);
            }));

            foreach(string file in files)
            {
                if (File.Exists(file))
                {
                    try
                    {
                        var clam = new ClamClient("localhost", 3310);
                        var scanResult = clam.ScanFileOnServer(file);
                        Invoke(new Action(() =>
                        {
                            curr_File.Text = file;
                        }));
                        
                        switch (scanResult.Result)
                        {
                            case ClamScanResults.VirusDetected:
                                infected++;
                                Invoke(new Action(() =>
                                {
                                    infec.Text = "感染的文件数: " + infected.ToString();
                                }));
                                AddToResult(file, scanResult.InfectedFiles.First().VirusName);
                                break;
                        }
                    }
                    catch { error = true; }

                }
                Invoke(new Action(() =>
                {
                    metroProgressBar1.Value = (metroProgressBar1.Value + 1);
                }));
                
            }
            if (infected > 0)
            {
                // virus found
                SoundPlayer snd = new SoundPlayer(Properties.Resources.virfound);
                snd.Play();
                Invoke(new Action(() =>
                {
                    objectListView1.Visible = true;
                    objectListView1.Show();
                    //listView1.Visible = true;
                    //listView1.Show();
                    metroTabControl1.SelectedIndex = 2;
                }));
                
            }

            if(error)
            {
                /*
                Invoke(new Action(() =>
                {
                    metroTabControl1.SelectedIndex = 0;
                    pictureBox1.Image = Properties.Resources.unsecured;
                    pictureBox3.Image = Properties.Resources.cross;
                }));
                
                MetroFramework.MetroMessageBox.Show(this, "There is a problem with scanner engine, kindly restart the antivirus", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                 */
            }

            files = null; // allow garbage collector to collect it
            Invoke(new Action(() =>
            {
                metroProgressSpinner1.Visible = false;
                metroProgressBar1.Value = 0;
                metroLabel8.Text = "没有进行中的扫描...";
                infec.Text = "感染的病毒数: 0";
                metroTile2.Enabled = false;
                metroTile3.Enabled = false;
                metroTile1.Enabled = true;
                curr_File.Text = "...";
                metroRadioButton2.Enabled = true;
                metroRadioButton3.Enabled = true;
                metroRadioButton4.Enabled = true;
            }));
            
            scanning = false;
            log.Info("结束扫描路径:" + loc_to_search);

            try
            {
                search.Abort();
            }
            catch { }
        }

        // check if a path is drive or not
        public static bool IsLogicalDrive(string path)
        {
            bool IsRoot = false;
            DirectoryInfo d = new DirectoryInfo(path);
            if (d.Parent == null) { IsRoot = true; }
            return IsRoot;
        }

        // get the files from the given path
        public string[] getFiles(string SourceFolder, string Filter, System.IO.SearchOption searchOption)
        {
            ArrayList alFiles = new ArrayList();
            string[] MultipleFilters = Filter.Split('|');
            try
            {
                if (IsLogicalDrive(SourceFolder))
                {
                    foreach (string d in Directory.GetDirectories(SourceFolder))
                    {
                        foreach (string FileFilter in MultipleFilters)
                        {
                            try
                            {
                                alFiles.AddRange(Directory.GetFiles(d, FileFilter, searchOption));
                            }
                            catch { continue; }
                        }
                    }
                }
                else
                {
                    foreach (string FileFilter in MultipleFilters)
                    {
                        try
                        {
                            alFiles.AddRange(Directory.GetFiles(SourceFolder, FileFilter, searchOption));
                        }
                        catch { continue; }
                    }
                }
            }
            catch
            {
                log.Error("无法访问USB盘");
            }


            return (string[])alFiles.ToArray(typeof(string));
        }

        //delete the found virus
        private void metroTile4_Click(object sender, EventArgs e)
        {
            string path = string.Empty;
            for (int i = 0; i < objectListView1.Items.Count; i++)
            {
                path = objectListView1.Items[i].SubItems[0].Text;
                try
                {
                    KillProcess(this.Handle, path); // try to kill the process before deleting it
                    File.Delete(path);
                }
                catch { }
            }
            objectListView1.Items.Clear();
        }

        //pause the on going scanning
        private void metroTile2_Click(object sender, EventArgs e)
        {
            if (scanning)
            {
                if (suspended)
                {
                    try
                    {
                        search.Resume();
                        suspended = false;
                        metroTile2.Text = "暂停";
                    }
                    catch { }
                }
                else
                {
                    try
                    {
                        search.Suspend();
                        metroTile2.Text = "恢复";
                        suspended = true;
                    }
                    catch { }
                }
            }
        }

        //stop the on going scanning
        private void metroTile3_Click(object sender, EventArgs e)
        {
            if(scanning)
            {
                try
                {
                    files = null;
                    metroProgressSpinner1.Visible = false;
                    metroProgressBar1.Value = 0;
                    scanning = false;
                    curr_File.Text = "...";
                    metroLabel8.Text = "没有进行中的扫描...";
                    infec.Text = "感染的文件数: 0";
                    curr_File.Text = "...";
                    metroTile2.Enabled = false;
                    metroTile3.Enabled = false;
                    metroTile1.Enabled = true;
                    metroRadioButton2.Enabled = true;
                    metroRadioButton3.Enabled = true;
                    metroRadioButton4.Enabled = true;
                    search.Abort();
                }
                catch { }
            }
        }

        private void metroTabControl2_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (metroTabControl2.SelectedTab == metroTabPageUpd)
            {
                // 更新Label的文本
                this.metroLabelUpdtime.Text = GetNewestUpdateTimeInDBDirectory();
            }
        }
        //show about from system tray
        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Show();
            this.Visible = true;
            metroTabControl1.SelectedIndex = 4;
        }

        //exit from system tray
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        //show hide from system tray
        private void showHideToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.Visible)
                this.Hide();
            else
            {
                this.Show();
                this.Visible = true;
            }
        }

        //mouse double click on system tray icon
        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            showHideToolStripMenuItem_Click(sender, e);
        }

        // handles the new usb disk add
        private void DoStateChanged(UsbStateChangedEventArgs e)
        {
            if (e.State == UsbStateChange.Added)
            {
               if(!scanning)
               {
                   if (listenUSB.Checked)
                   {
                       loc_to_search = e.Disk.Name;
                       search = new Thread(new ThreadStart(ScanFolder));
                       search.Start();
                       metroTabControl1.SelectedIndex = 1;
                   }
               }
            }
        }

        //real time scanning, toggle event
        private void realToggle_CheckedChanged(object sender, EventArgs e)
        {
            if (realToggle.Checked)
            {
                metroLabel14.Text = "实时扫描...";
                pictureBox6.Image = Properties.Resources.fine;
                pictureBox3.Image = Properties.Resources.fine;
                pictureBox1.Image = Properties.Resources.secured;
            }
            else
            {
                metroLabel14.Text = "未使能实时扫描";
                pictureBox6.Image = Properties.Resources.cross;
                pictureBox3.Image = Properties.Resources.cross;
                pictureBox1.Image = Properties.Resources.unsecured;
            }

        }

        //auto usb scan toggle
        private void listenUSB_CheckedChanged(object sender, EventArgs e)
        {
            if (listenUSB.Checked)
                pictureBox7.Image = Properties.Resources.fine;
            else
                pictureBox7.Image = Properties.Resources.cross;
        }

        //update
        //更新病毒库，使用clamav.net 99%链接失败
        //TODO:寻找一个合适的clamav db数据源
        private void metroTile5_freshClick(object sender, EventArgs e)
        {
            log.Info("开始更新病毒库");
            string engdir = my_location + "\\engine\\";
            // freshclam 是 ClamAV 的命令行工具，用于更新病毒库
            var processStartInfo = new ProcessStartInfo
            {
                            //setup the scanner engine path
                FileName = engdir + "freshclam.exe",
                Arguments = "", // 或者其他的更新参数，如"--quiet"减少输出
                RedirectStandardOutput = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };

            using (Process process = new Process())
            {
                process.StartInfo = processStartInfo;
                
                // 启动更新进程
                process.Start();

                // 等待进程结束
                process.WaitForExit();

                // 输出更新日志（可选）
                string output = process.StandardOutput.ReadToEnd();
                //Console.WriteLine(output);
                log.Info("病毒库更新结果:"+ output);
            }
        }
        public static void DeleteFilesInDirectory(string directoryPath)
        {
            if (!Directory.Exists(directoryPath))
            {
                // 目录不存在，则无需删除
                return;
            }

            // 获取目录信息
            DirectoryInfo dir = new DirectoryInfo(directoryPath);

            // 遍历并删除所有文件
            foreach (FileInfo file in dir.GetFiles())
            {
                file.Attributes = FileAttributes.Normal; // 先移除只读属性，以便能够删除文件
                file.Delete(); // 删除文件
            }
        }
        // 合并文件示例（仅作参考）
        public static void ConcatenateFiles(string dbdir, string[] sourceFiles, string destinationFile)
        {
            using (FileStream destinationStream = new FileStream(dbdir + destinationFile, FileMode.Create))
            {
                foreach (string sourceFile in sourceFiles)
                {
                    if (File.Exists(dbdir + sourceFile))
                    {
                        using (FileStream sourceFileStream = new FileStream(dbdir + sourceFile, FileMode.Open))
                        {
                            sourceFileStream.CopyTo(destinationStream);
                        }
                    }
                    else
                    {
                        Console.WriteLine($"源文件 {sourceFile} 不存在，跳过...");
                    }
                }
            }
            log.Info("合并病毒库:" + destinationFile);
        }

        // 在下载完成后调用此方法合并文件
        private void MergeMainCvdParts(string saveFolderPath)
        {
            string[] sourceFiles = new[]
            {
                @"main.cvd.01",
                @"main.cvd.02",
                @"main.cvd.03",
                @"main.cvd.04",
                @"main.cvd.05",
                @"main.cvd.06",
                @"main.cvd.07",
                @"main.cvd.08",
                @"main.cvd.09",
                @"main.cvd.10"
            };

            string destinationFile = @"main.cvd";

            ConcatenateFiles(saveFolderPath, sourceFiles, destinationFile);
            string[] dsourceFiles = new[]
            {
                @"daily.cvd.01",
                @"daily.cvd.02",
                @"daily.cvd.03",
                @"daily.cvd.04",
                @"daily.cvd.05",
                @"daily.cvd.06",
                @"daily.cvd.07",
                @"daily.cvd.08",
                @"daily.cvd.09",
                @"daily.cvd.10"
            };

            string ddestinationFile = @"daily.cvd";

            ConcatenateFiles(saveFolderPath , dsourceFiles, ddestinationFile);
        }
        public static async Task DownloadFilesToListAsync(string[] urls, string saveFolderPath)
        {
            using (var httpClient = new HttpClient())
            {
                foreach (string url in urls)
                {
                    // 分离出文件名
                    string filename = Path.GetFileName(new Uri(url).AbsolutePath);

                    // 指定本地保存路径
                    string localFilePath = Path.Combine(saveFolderPath, filename);

                    // 下载文件
                    HttpResponseMessage response = await httpClient.GetAsync(url);
                    response.EnsureSuccessStatusCode();

                    using (Stream contentStream = await response.Content.ReadAsStreamAsync())
                    using (FileStream fs = File.Create(localFilePath))
                    {
                        await contentStream.CopyToAsync(fs);
                    }
                    log.Info("下载URL：" + url);
                   // Console.WriteLine($"File {filename} has been downloaded successfully.");
                }
            }
        }

        private static bool VerifySha256(string fileName, string checksumFileName)
        {
            using (var sha256 = SHA256.Create())
            {
                byte[] fileData = File.ReadAllBytes(fileName);
                string actualChecksum = BitConverter.ToString(sha256.ComputeHash(fileData)).Replace("-", "").ToLowerInvariant();

                string expectedChecksum = File.ReadAllText(checksumFileName);
                return actualChecksum == expectedChecksum;
            }
        }
        //改用github作为数据更新源
       private void metroTile5_Click(object sender, EventArgs e)
        {
            metroTile5.Enabled = false;
            log.Info("开始更新病毒库(gitee源)");
            //rm -f main.cvd daily.cld daily.cvd bytecode.cvd main.cvd.sha256 daily.cvd.sha256 bytecode.cvd.sha256 main.cvd.* daily.cvd.* 
            // && curl -LSOs https://github.com/ladar/clamav-data/raw/main/main.cvd.[01-10] -LSOs https://github.com/ladar/clamav-data/raw/main/main.cvd.sha256 
            //-LSOs https://github.com/ladar/clamav-data/raw/main/daily.cvd.[01-10] -LSOs https://github.com/ladar/clamav-data/raw/main/daily.cvd.sha256 
            //-LSOs https://github.com/ladar/clamav-data/raw/main/bytecode.cvd 
            //-LSOs https://github.com/ladar/clamav-data/raw/main/bytecode.cvd.sha256 
            //&& cat main.cvd.01 main.cvd.02 main.cvd.03 main.cvd.04 main.cvd.05 main.cvd.06 main.cvd.07 main.cvd.08 main.cvd.09 main.cvd.10 > main.cvd 
            //&& cat daily.cvd.01 daily.cvd.02 daily.cvd.03 daily.cvd.04 daily.cvd.05 daily.cvd.06 daily.cvd.07 daily.cvd.08 daily.cvd.09 daily.cvd.10 > daily.cvd 
            //&& sha256sum -c main.cvd.sha256 daily.cvd.sha256 bytecode.cvd.sha256 || { printf "ClamAV database download failed.\n" ; rm -f main.cvd daily.cvd bytecode.cvd ; } ;
            // rm -f main.cvd.sha256 daily.cvd.sha256 bytecode.cvd.sha256 main.cvd.* daily.cvd.*

            Task.Run(async () =>
            {
                string dbdir = my_location + "\\engine\\DB\\";
                DeleteFilesInDirectory(dbdir);
                //string web = "https://github.com/ladar/clamav-data/raw/main/";
                string web = "https://gitee.com/colornix/clamav-data/releases/download/2024.03.02/";
                string webmain = "https://gitee.com/colornix/clamav-data/releases/download/2024.03.03/";
                string[] urls = {
                    web + "main.cvd.01",
                    web + "main.cvd.02",
                    web + "main.cvd.03",
                    web + "main.cvd.04",
                    web + "main.cvd.05",
                    web + "main.cvd.06",
                    webmain + "main.cvd.07",                        
                    webmain + "main.cvd.08",
                    webmain + "main.cvd.09",
                    webmain + "main.cvd.10",                        
                                            // ... 依此类推，直到main.cvd.10
                    webmain + "main.cvd.sha256",
                    web + "daily.cvd.01",
                    web + "daily.cvd.02",
                    web + "daily.cvd.03",
                    web + "daily.cvd.04",
                    web + "daily.cvd.05",
                    web + "daily.cvd.06",
                    web + "daily.cvd.07",
                    web + "daily.cvd.08",
                    web + "daily.cvd.09",
                    web + "daily.cvd.10",
                    // ... 依此类推，直到daily.cvd.10
                    web + "daily.cvd.sha256",
                    web + "bytecode.cvd",
                    web + "bytecode.cvd.sha256"
                };
                // 调试的时候不用下载，直接合并
                await DownloadFilesToListAsync(urls, dbdir);
                // 确保在后台任务完成后再进行UI相关的操作


                // 合并文件部分也可以在此处调用，但确保是在InvokeAsync内部
                MergeMainCvdParts(dbdir);
                // 验证SHA256
                if (!VerifySha256("main.cvd", "main.cvd.sha256") ||
                    !VerifySha256("daily.cvd", "daily.cvd.sha256") 
                    ||!VerifySha256("bytecode.cvd", "bytecode.cvd.sha256")
                    )
                {
                    log.Info("ClamAV database download failed.");
                    //DeleteFiles("main.cvd", "daily.cvd", "bytecode.cvd");
                }
                log.Info("病毒库更新完成");
                //FIXME: restart clamd service, not tested.
                string status = string.Empty;
                service.ServiceName = "ClamD";
                service.Stop();
                service.Start();
                status = service.Status.ToString();
                if (status!= "Running"){
                    log.Error("Clamd service failed to run");
                }
                metroTile5.Enabled = true;
            });


        }
        //Real time scanner 
        private void RealTime(object sender, FileSystemEventArgs e)
        {
            if (av_service_error)
                return;
            if (exclusion.isExclusion(e.FullPath))
                return;

            FileAttributes attr;
            int inf = 0;
            try
            {
                if (realToggle.Checked)
                {
                    //log.Debug("开始实时扫描：" + e.FullPath);
                    Invoke(new Action(() =>
                    {
                        metroLabel13.Text = e.FullPath;
                    }));

                    attr = File.GetAttributes(e.FullPath);
                    if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
                    {
                        //give some to create the whole dir at once...
                        Thread.Sleep(3000);
                        //Now start scanning the folder

                        string[] fls = getFiles(e.FullPath, wildcard, SearchOption.AllDirectories);
                        if(fls!=null)
                        {
                            //MessageBox.Show(fls.Length.ToString());
                            foreach(string s in fls)
                            {
                                if(File.Exists(s))
                                {
                                    var clam = new ClamClient("localhost", 3310);
                                    var scanResult = clam.ScanFileOnServer(s);
                                    switch (scanResult.Result)
                                    {
                                        case ClamScanResults.VirusDetected:
                                            {
                                                inf++;
                                                AddToResult(s, scanResult.InfectedFiles.First().VirusName);
                                                Invoke(new Action(() =>
                                                {
                                                    objectListView1.Visible = true;
                                                    objectListView1.Show();
                                                    this.Visible = true;
                                                    this.Show();
                                                    metroTabControl1.SelectedIndex = 2;
                                                }));

                                            }
                                            break;
                                    }
                                }
                            }
                            //Every found virus is listed, now play sound
                            if(inf>0)
                            {
                                SoundPlayer snd = new SoundPlayer(Properties.Resources.virfound);
                                snd.Play();
                            }
                        }
                        
                    }
                    else
                    {
                        //it's a file let's scan it...
                        var clam = new ClamClient("localhost", 3310);
                        var scanResult = clam.ScanFileOnServer(e.FullPath);
                        switch (scanResult.Result)
                        {
                            case ClamScanResults.VirusDetected:
                                {
                                    AddToResult(e.FullPath, scanResult.InfectedFiles.First().VirusName);
                                    SoundPlayer snd = new SoundPlayer(Properties.Resources.virfound);
                                    snd.Play();
                                    Invoke(new Action(() =>
                                    {
                                        objectListView1.Visible = true;
                                        objectListView1.Show();
                                        this.Visible = true;
                                        this.Show();
                                        metroTabControl1.SelectedIndex = 2;
                                    }));
                                }
                                break;
                        }
                    }
                }
            }
            catch { }
            //log.Debug("结束实时扫描");
        }

        //folder permission checks
        public static bool HasFolderWritePermission(string path)
        {
            int c = 0;
            try
            {
                DirectoryInfo di = new DirectoryInfo(path);
                DirectorySecurity acl = di.GetAccessControl();
                AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount));

                WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
                WindowsPrincipal principal = new WindowsPrincipal(currentUser);
                foreach (AuthorizationRule rule in rules)
                {
                    FileSystemAccessRule fsAccessRule = rule as FileSystemAccessRule;
                    if (fsAccessRule == null)
                        continue;

                    if ((fsAccessRule.FileSystemRights & FileSystemRights.WriteData) > 0)
                    {
                        NTAccount ntAccount = rule.IdentityReference as NTAccount;
                        if (ntAccount == null)
                        {
                            continue;
                        }
                        if (principal.IsInRole(ntAccount.Value))
                        {
                            c++;
                            continue;
                        }
                    }
                }
                if (c > 0) return true;
                else return false;
            }
            catch { return false; }
        }

        //quick scan from system tray
        private void scanToolStripMenuItem_Click(object sender, EventArgs e)
        {
            metroRadioButton2.Checked = true;
            metroTile1_Click(sender, e);
        }

        // main minimize button on form
        private void metroTile6_Click(object sender, EventArgs e)
        {
            if (this.Visible)
                this.Hide();
        }

        //firewall on off
        private void metroToggle1_CheckedChanged(object sender, EventArgs e)
        {
            if(firewallToggle.Checked)
            {
                fw.FirewallStart(true);
                pictureBox2.Image = Properties.Resources.fine;
                metroLabel2.Text = "防火墙已启用";
            }
            else
            {
                con.RunExternalExe("netsh.exe", "Firewall set opmode disable");
                pictureBox2.Image = Properties.Resources.cross;
                metroLabel2.Text = "防火墙已关闭";
            }
        }

        //clear the history
        private void metroTile7_Click(object sender, EventArgs e)
        {
            his.DelHistory();
            objectListView2.ClearObjects();
        }

        // move selected viruses to Quarantine
        private void metroTile8_Click(object sender, EventArgs e)
        {
            if(objectListView1.Items.Count>0)
            {
                int count = objectListView1.CheckedObjects.Count;
                if (count > 0)
                {
                    for (int i = 0; i < objectListView1.Items.Count; i++)
                    {
                        if (objectListView1.Items[i].Checked)
                        {
                            string path = quaran.AddQuarantine(objectListView1.Items[i].SubItems[0].Text);
                            listBox2.Items.Add(path);
                            try
                            {
                                File.Delete(objectListView1.Items[i].SubItems[0].Text);
                            }
                            catch { }
                        }
                    }
                    MetroFramework.MetroMessageBox.Show(this, "选择的项已经被移入隔离区", "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    //objectListView1.UncheckAll();
                }
                else
                    MetroFramework.MetroMessageBox.Show(this, "没有选中项。请选中一项移入隔离区", "警告", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }

        //restore selected quarantine item
        private void restoreThisItemToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if(listBox2.Items.Count>0)
            {
                if (listBox2.SelectedItems.Count > 0)
                {
                    string path = listBox2.Items[listBox2.SelectedIndex].ToString();
                    if (File.Exists(path))
                    {
                        DialogResult dr = MetroFramework.MetroMessageBox.Show(this, "Do you want to restore the selcted item? Restoring viruses may infect your system, do you still want to restore it?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                        if(dr == DialogResult.Yes)
                        {
                            folderBrowserDialog1.Description = "选择要保存到的文件夹或驱动器";
                            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
                            {
                                quaran.RestoreQuarantine(path, folderBrowserDialog1.SelectedPath);
                                listBox2.Items.RemoveAt(listBox2.SelectedIndex);
                            }
                        }
                    }
                    else
                        MetroFramework.MetroMessageBox.Show(this, "选中的项不存在，无法恢复该项", "无法恢复", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                }
            }
        }

        //Delete the selected quarantine file
        private void deleteThisItemToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (listBox2.Items.Count > 0)
            {
                if (listBox2.SelectedItems.Count > 0)
                {
                    string path = listBox2.Items[listBox2.SelectedIndex].ToString();
                    if (File.Exists(path))
                    {
                        try { File.Delete(path); }
                        catch { }
                        listBox2.Items.RemoveAt(listBox2.SelectedIndex);
                    }
                    else
                        MetroFramework.MetroMessageBox.Show(this, "选中的项不存在，无法恢复该项", "无法恢复", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                }
            }
        }

        //clear all quarantine
        private void metroTile9_Click(object sender, EventArgs e)
        {
            quaran.ClearQuarantine();
            listBox2.Items.Clear();
        }

        //scheduled scanning
        private void scheduledToggle_CheckedChanged(object sender, EventArgs e)
        {
            if (scheduledToggle.Checked)
            {
                if(metroRadioButton1.Checked)
                {
                    //custom folder
                    folderBrowserDialog1.Description = "选择文件夹或者驱动器";
                    if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
                    {
                        sch_loc = folderBrowserDialog1.SelectedPath;
                        sch_time = dateTimePicker1.Value;
                        timer1.Interval = 1000;
                        timer1.Start();
                        dateTimePicker1.Enabled = false;
                        metroRadioButton1.Enabled = false;
                        metroRadioButton5.Enabled = false;
                        metroLabel22.Text = "指定扫描: " + sch_loc;
                        return;
                    }
                }
                if(metroRadioButton5.Checked)
                {
                    //quick
                    sch_loc = Path.GetPathRoot(Environment.SystemDirectory);
                    sch_time = dateTimePicker1.Value;
                    timer1.Interval = 1000;
                    timer1.Start();
                    dateTimePicker1.Enabled = false;
                    metroRadioButton1.Enabled = false;
                    metroRadioButton5.Enabled = false;
                    metroLabel22.Text = "创建了快速扫描计划";
                    return;
                }
                scheduledToggle.Checked = false;
                MetroFramework.MetroMessageBox.Show(this, "扫描计划需要先指定扫描类型", "警告", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            else
            {
                dateTimePicker1.Enabled = true;
                metroRadioButton1.Enabled = true;
                metroRadioButton5.Enabled = true;
                metroLabel22.Text = "没有扫描计划";
                timer1.Stop();
            }
        }

        //scheduled scanning timer
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (sch_time.Hour == DateTime.Now.Hour && sch_time.Minute == DateTime.Now.Minute && sch_time.ToString("tt") == DateTime.Now.ToString("tt"))
            {
                //time matched...
                if(!scanning)
                {
                    dateTimePicker1.Enabled = true;
                    metroRadioButton1.Enabled = true;
                    metroRadioButton5.Enabled = true;
                    metroLabel22.Text = "没有扫描计划";
                    scheduledToggle.Checked = false;
                    timer1.Stop();
                    metroTabControl1.SelectedIndex = 1;
                    loc_to_search = sch_loc;
                    search = new Thread(new ThreadStart(ScanFolder));
                    search.Start();
                    if (metroRadioButton1.Checked)
                        metroRadioButton4.Checked = true;
                    if (metroRadioButton5.Checked)
                        metroRadioButton2.Checked = true;
                }
            }
        }

        //returns all the running processes path
        private List<string> GetAllRunningProcesses()
        {
            List<string> list = new List<string>();
            var wmiQueryString = "SELECT ProcessId, ExecutablePath, CommandLine FROM Win32_Process";
            using (var searcher = new ManagementObjectSearcher(wmiQueryString))
            using (var results = searcher.Get())
            {
                var query = from p in Process.GetProcesses()
                            join mo in results.Cast<ManagementObject>()
                            on p.Id equals (int)(uint)mo["ProcessId"]
                            select new
                            {
                                Process = p,
                                Path = (string)mo["ExecutablePath"],
                                CommandLine = (string)mo["CommandLine"],
                            };
                foreach (var item in query)
                {
                    list.Add(item.Path);
                }
            }
            return list;
        }

        //add folder in exclusion
        private void metroTile11_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.Description = "选择文件夹或驱动器";
            if(folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                exclusion.AddExclusion(folderBrowserDialog1.SelectedPath);
                listBox3.Items.Add(folderBrowserDialog1.SelectedPath);
            }
        }

        //add a file in exclusion
        private void metroTile10_Click(object sender, EventArgs e)
        {
            openFileDialog1.Title = "请选择文件";
            openFileDialog1.Multiselect = false;
            openFileDialog1.CheckPathExists = true;
            openFileDialog1.FileName = "";
            openFileDialog1.Filter = "All files|*.*";
            openFileDialog1.SupportMultiDottedExtensions = false;

            if (DialogResult.OK == openFileDialog1.ShowDialog())
            {
                exclusion.AddExclusion(openFileDialog1.FileName);
                listBox3.Items.Add(openFileDialog1.FileName);
            }
        }

        //clears all the exclusion
        private void metroTile12_Click(object sender, EventArgs e)
        {
            exclusion.ClearExclusion();
            listBox3.Items.Clear();
        }

        //save db selection
        private void metroTileUpd_Click(object sender, EventArgs e)
        {
            try{
                // 获取 metroTextBoxDatabaseUrl 中的文本内容
                string databaseUrl = metroTxtMirr.Text.Trim();
                string dns = metroTxtDns.Text.Trim();    
                //setup the scanner engine path
                string temp = my_location + "\\engine\\";        
                //write the correct engine configurations according to path
                StreamWriter upwritter = new StreamWriter(temp + "freshclam.conf");
                upwritter.WriteLine("DatabaseMirror " + databaseUrl);
                upwritter.WriteLine("DNSDatabaseInfo " + dns);
                upwritter.WriteLine("UpdateLogFile " + temp + "freshclam.log");
                upwritter.Close();
                string status = string.Empty;
                service.ServiceName = "FreshClam";
                service.Stop();
                service.Start();
                this.metroLabelUpdtime.Text = GetNewestUpdateTimeInDBDirectory();
                log.Info("freshclam service restarted");
            }
            catch (InvalidOperationException ex)
            {
                // 当服务操作无效时（例如服务不存在或状态不允许进行停止或启动操作）
                Console.WriteLine($"发生异常：{ex.Message}");
                log.Warn($"freshclam service does not run, reason: {ex.Message}");
            }
            catch (Exception ex)
            {
                // 捕获所有其他未知异常
                Console.WriteLine($"发生未知异常：{ex.Message}");
                log.Warn($"freshclam service does not run, reason: {ex.Message}");
            }
        }
        //remove a selected exclusion
        private void removeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (listBox3.Items.Count > 0)
            {
                if (listBox3.SelectedItems.Count > 0)
                {
                    string path = listBox3.Items[listBox3.SelectedIndex].ToString();
                    exclusion.DelExclusion(path);
                    listBox3.Items.RemoveAt(listBox3.SelectedIndex);
                }
            }
        }

        //remove the vault
        private void metroTile14_Click(object sender, EventArgs e)
        {
            if (locker.no_valut)
                MetroFramework.MetroMessageBox.Show(this, "没有可移除的保险库", "警告", MessageBoxButtons.OK, MessageBoxIcon.Information);
            else
            {
                DialogResult dr = MetroFramework.MetroMessageBox.Show(this, "删除保险库将会删除其中的所有文件，请首先备份您的文件。\n您要删除保险库吗?", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (dr == DialogResult.Yes)
                    locker.DestroyFolder(this);
            }
        }

        //vault lock or create
        private void metroTile13_Click(object sender, EventArgs e)
        {
            locker.CreateOrUnlockFolder(this);
        }

        //lock the opened vault
        private void metroTile15_Click(object sender, EventArgs e)
        {
            locker.LockFolder(this);
        }


    } //end of class
} //end of namespace
